#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <fcntl.h>
#include <unistd.h>
#include <arpa/inet.h>
#include "common.h"
#include "ofprint_common.h"
#include "usb_device.h"
#include "app_fp256_360.h"


PROT_PACKET prot_packet_usb;	//报文协议处理结构
FP_DEVICE_PARAM_STRUCT fp_device_param;


uint8  usb_recv_data[USB_BUFFER_SIZE];
uint16 usb_recv_cnt = 0;

/********************函数预定义********************/
int32 fp_upload_fprint_img(void);
int32 fp_onekey_restart_identify(uint16 *identify_result_id, int32 wait_ms);
/**************************************************/


int32 fp_module_init(void)
{
	memset((uint8 *)&prot_packet_usb, 0, sizeof(PROT_PACKET));
	memset((uint8 *)&fp_device_param, 0, sizeof(FP_DEVICE_PARAM_STRUCT));
	WD_DBG("success.\r\n");
	return DRV_OK;
}

/*取得校验和*/
uint16 get_check_sum(uint8 *buf, uint16 len)
{
	uint32 i = 0;
	uint16 checksum = 0;

	if (NULL == buf)
	{
		WD_ERR("the point buf is null, error!!!\r\n");
		return 0;
	}

	for (i = 0; i < len; i++)
	{
		checksum += buf[i];
	}

	return (checksum);
}


int32 fp_recv_param_init(RECV_DATA_STRUCT *recv_param, int32 recv_len, uint16 wait_ms, uint16 cycle_times, uint16 cycle_ms)
{
	if(NULL == recv_param)
	{
		WD_ERR("the point recv_param is null, error!!!\r\n");
		return DRV_ERR;
	}

	memset((uint8 *)recv_param, 0x00, sizeof(RECV_DATA_STRUCT));

	recv_param->recv_len = recv_len;
	recv_param->wait_ms = wait_ms;
	recv_param->cycle_times = cycle_times;
	recv_param->cycle_ms = cycle_ms;

	return DRV_OK;
}



int32 fp_resp_init(uint8 cmd_code)
{
	PROT_PACKET *p = &prot_packet_usb;

	p->current_cmd_code = cmd_code;
	p->current_resp_cmd = 0;
	p->current_resp_type = 0xff;

	return DRV_OK;
}

uint8 fp_resp_type_get(void)
{
	PROT_PACKET *p = &prot_packet_usb;

	return p->current_resp_type;
}


int32 fp_parse_prot_response(uint8 *buf, int32 len)
{
	uint8 current_cmd_code = prot_packet_usb.current_cmd_code;
	uint8 confirm_code = 0;
	PROT_PACKET *p = &prot_packet_usb;
	FP_DEVICE_PARAM_STRUCT *dev_param = &fp_device_param;

	if((NULL == buf) || (0 >= len))
	{
		WD_ERR("the param is error!!!\r\n");
		return DRV_ERR;
	}

	confirm_code = buf[0];
	p->current_resp_type = confirm_code;

	switch(current_cmd_code)
	{
		case PROT_CMD_GETIMAGE:		//验证用获取图像
			DBG("%s:%d:%s: received PROT_CMD_GETIMAGE response.\r\n", __FILE__, __LINE__, __func__);
			p->current_resp_cmd = PROT_CMD_GETIMAGE;
			break;
		case PROT_CMD_GENCHAR:break;		//根据原始图像生成指纹特征存于文件缓冲区
		case PROT_CMD_MATCH:break;			//精确比对特征文件缓冲区中的特征文件
		case PROT_CMD_SEARCH:break; 		//以特征文件缓冲区中的特征文件搜索整个或部分指纹库
		case PROT_CMD_REGMODEL:break;		//将特征文件合并生成模板存于特征文件缓冲区
		case PROT_CMD_STORECHAR:break;		//将特征缓冲区中的文件储存到flash指纹库中
		case PROT_CMD_LOADCHAR:break;		//从 flash 指纹库中读取一个模板到特征缓冲区
		case PROT_CMD_UPCHAR:break; 		//将特征缓冲区中的文件上传给上位机
		case PROT_CMD_DOWNCHAR:break;		//从上位机下载一个特征文件到特征缓冲区
		case PROT_CMD_UPIMAGE:		//上传原始图像
			DBG("%s:%d:%s: received PROT_CMD_UPIMAGE response.\r\n", __FILE__, __LINE__, __func__);
			p->current_resp_cmd = PROT_CMD_UPIMAGE;
			break;
		case PROT_CMD_DOWNIMAGE:break;		//下载原始图像
		case PROT_CMD_DELCHAR:		//删除 flash 指纹库中的一个特征文件
			DBG("%s:%d:%s: received PROT_CMD_DELCHAR response.\r\n", __FILE__, __LINE__, __func__);
			p->current_resp_cmd = PROT_CMD_DELCHAR;
			dev_param->delete_template_result = confirm_code;
			break;
		case PROT_CMD_EMPTY:			//清空 flash 指纹库
			DBG("%s:%d:%s: received PROT_CMD_EMPTY response.\r\n", __FILE__, __LINE__, __func__);
			p->current_resp_cmd = PROT_CMD_EMPTY;
			dev_param->empty_template_result = confirm_code;
			break;
		case PROT_CMD_READSYSPARA:	//读系统基本参数
			DBG("%s:%d:%s: received PROT_CMD_READSYSPARA response.\r\n", __FILE__, __LINE__, __func__);
			p->current_resp_cmd = PROT_CMD_READSYSPARA;
			dev_param->sys_param.sensor_type = ((buf[1]<<8) & 0xff00) | (buf[2] & 0x00ff);
			dev_param->sys_param.fp_database_size = ((buf[3]<<8) & 0xff00) | (buf[4] & 0x00ff);
			dev_param->sys_param.security_level = ((buf[5]<<8) & 0xff00) | (buf[6] & 0x00ff);
			dev_param->sys_param.device_addr = ((buf[7]<<24) & 0xff000000) \
												| ((buf[8]<<16) & 0x00ff0000) \
												| ((buf[9]<< 8) & 0x0000ff00) \
												| (buf[10] & 0x000000ff);
			DBG("%s:%d:%s: sensor_type = 0x%04x, fp_database_size = 0x%04x, security_level = 0x%04x, device_addr = 0x%08x.\r\n", \
				__FILE__, __LINE__, __func__, dev_param->sys_param.sensor_type, dev_param->sys_param.fp_database_size, \
				dev_param->sys_param.security_level, dev_param->sys_param.device_addr);
			break;
		case PROT_CMD_SETPWD:break; 		//设置设备握手口令
		case PROT_CMD_VFYPWD:break; 		//验证设备握手口令

		case PROT_CMD_SETCHIPADDR:	//设置芯片地址
			DBG("%s:%d:%s: received PROT_CMD_SETCHIPADDR response.\r\n", __FILE__, __LINE__, __func__);
			p->current_resp_cmd = PROT_CMD_SETCHIPADDR;
			break;
		case PROT_CMD_READINFOPAGE:	//读取 FLASH Information Page 内容
			DBG("%s:%d:%s: received PROT_CMD_READINFOPAGE response.\r\n", __FILE__, __LINE__, __func__);
			p->current_resp_cmd = PROT_CMD_READINFOPAGE;
			break;
		case PROT_CMD_HIGHSPEEDSEARCH:break;	//高速搜索FLASH
		case PROT_CMD_VALIDTEMPLATENUM:	//读有效模板个数
			DBG("%s:%d:%s: received PROT_CMD_VALIDTEMPLATENUM response.\r\n", __FILE__, __LINE__, __func__);
			if(PROT_RESP_OK == confirm_code)
			{
				dev_param->valid_template_num = ((buf[1]<<8) & 0xff00) | (buf[2] & 0x00ff);
			}
			p->current_resp_cmd = PROT_CMD_VALIDTEMPLATENUM;
			break;
		case PROT_CMD_READINDEXTABLE: 	//读索引表
			DBG("%s:%d:%s: received PROT_CMD_READINDEXTABLE response.\r\n", __FILE__, __LINE__, __func__);
			p->current_resp_cmd = PROT_CMD_READINDEXTABLE;
			if(4 > dev_param->index_table_page)
			{
				memcpy(dev_param->index_table_info[dev_param->index_table_page], buf + 1, 32);
				{
					for(int16 i = 0; i < 32; i++)
					{
						DBG("%02x ", dev_param->index_table_info[dev_param->index_table_page][i]);
					}
					DBG("\r\n");
				}
			}
			break;
		case PROT_CMD_GETENROLLIMAGE:break; //注册用获取图像
		case PROT_CMD_CANCEL: 		//取消指令
			DBG("%s:%d:%s: received PROT_CMD_CANCEL response.\r\n", __FILE__, __LINE__, __func__);
			p->current_resp_cmd = PROT_CMD_CANCEL;
			dev_param->cancel_result = confirm_code;
			break;
		case PROT_CMD_AUTOENROLL: 	//自动注册模块指令
			D_DBG("received PROT_CMD_AUTOENROLL response.\r\n");
			p->current_resp_cmd = PROT_CMD_AUTOENROLL;
			switch(buf[1])
			{
				case 0x00:
					dev_param->auto_enroll_param.validity_check_result = confirm_code;
					D_DBG("validity_check_result = 0x%02x.\r\n", \
						dev_param->auto_enroll_param.validity_check_result);
					break;
				case 0x01:
					dev_param->auto_enroll_param.capture_result[buf[2]] = confirm_code;
					dev_param->auto_enroll_param.current_enroll_time = buf[2];
					D_DBG("capture_result[%d] = 0x%02x.\r\n", \
						buf[2], dev_param->auto_enroll_param.capture_result[buf[2]]);
					break;
				case 0x02:
					dev_param->auto_enroll_param.create_feature_result[buf[2]] = confirm_code;
					dev_param->auto_enroll_param.current_enroll_time = buf[2];
					D_DBG("create_feature_result[%d] = 0x%02x.\r\n", \
						buf[2], dev_param->auto_enroll_param.create_feature_result[buf[2]]);
					break;
				case 0x03:
					dev_param->auto_enroll_param.enroll_result[buf[2]] = confirm_code;
					dev_param->auto_enroll_param.current_enroll_time = buf[2];
					dev_param->auto_enroll_param.current_enroll_flag = 1;
					D_DBG("enroll_result[%d] = 0x%02x.\r\n", \
						buf[2], dev_param->auto_enroll_param.enroll_result[buf[2]]);
					break;
				case 0x04:
					dev_param->auto_enroll_param.merge_template_result = confirm_code;
					D_DBG("merge_template_result = 0x%02x.\r\n", \
						dev_param->auto_enroll_param.merge_template_result);
					//sleep(1);
					break;
				case 0x05:
					dev_param->auto_enroll_param.enroll_conflict_result = confirm_code;
					WD_DBG("enroll_conflict_result = 0x%02x.\r\n", \
						dev_param->auto_enroll_param.enroll_conflict_result);
					break;
				case 0x06:
					dev_param->auto_enroll_param.store_template_result = confirm_code;
					dev_param->auto_enroll_param.enroll_finish_flag = 1;
					WD_DBG("store_template_result = 0x%02x.\r\n", \
						dev_param->auto_enroll_param.store_template_result);
					break;
				default:
					WD_ERR("param buf[1] = 0x%02x, error!!!\r\n", buf[1]);
					break;
			}
			break;
		case PROT_CMD_AUTOIDENTIFY:	//自动验证指纹指令
			D_DBG("received PROT_CMD_AUTOIDENTIFY response.\r\n");
			p->current_resp_cmd = PROT_CMD_AUTOIDENTIFY;
			switch(buf[1])
			{
				case 0x00:
					dev_param->auto_identify_param.validity_check_result = confirm_code;
					D_DBG("validity_check_result = 0x%02x.\r\n", \
						dev_param->auto_identify_param.validity_check_result);
					break;
				case 0x01:
					dev_param->auto_identify_param.validity_check_result = PROT_RESP_OK;
					dev_param->auto_identify_param.capture_result = confirm_code;
					D_DBG("capture_result = 0x%02x.\r\n", \
						dev_param->auto_identify_param.capture_result);
					break;
				case 0x05:
					dev_param->auto_identify_param.validity_check_result = PROT_RESP_OK;
					dev_param->auto_identify_param.search_result = confirm_code;
					dev_param->auto_identify_param.search_num = 1;
					dev_param->auto_identify_param.search_id[0] = ((buf[2] << 8) & 0xff00) | (buf[3] & 0xff);
					dev_param->auto_identify_param.score = ((buf[4] << 8) & 0xff00) | (buf[5] & 0xff);
					dev_param->auto_identify_param.identify_finish_flag = 1;
					WD_DBG("search_result = 0x%02x, search_id[0] = 0x%04x.\n", \
						dev_param->auto_identify_param.search_result, dev_param->auto_identify_param.search_id[0]);
					break;
				case 0xf5:
					dev_param->auto_identify_param.search_result = confirm_code;
					dev_param->auto_identify_param.search_num = buf[2];
					for(int n = 0; n < dev_param->auto_identify_param.search_num; n++)
					{
						dev_param->auto_identify_param.search_id[n] = buf[3 + n];
					}
					dev_param->auto_identify_param.identify_finish_flag = 1;
					WD_DBG("search_result = 0x%02x, search_num = %d.\r\n", \
						dev_param->auto_identify_param.search_result, dev_param->auto_identify_param.search_num);
					break;
				default:
					WD_ERR("param buf[1] = 0x%02x, error!!!\r\n", buf[1]);
					break;
			}
			break;
		case PROT_CMD_SLEEP:			//休眠指令
			D_DBG("received PROT_CMD_SLEEP response.\r\n");
			p->current_resp_cmd = PROT_CMD_SLEEP;
			dev_param->sleep_result = confirm_code;
			break;
		case PROT_CMD_GETCHIPSN:		//获取芯片唯一序列号
			D_DBG("received PROT_CMD_GETCHIPSN response.\r\n");
			p->current_resp_cmd = PROT_CMD_GETCHIPSN;
			if(0x13 == p->prot_size)
			{
				dev_param->chip_serial_num_len = 16;
				memcpy(dev_param->chip_serial_num, buf + 1, 16);
			}
			else if(0x23 == p->prot_size)
			{
				dev_param->chip_serial_num_len = 32;
				memcpy(dev_param->chip_serial_num, buf + 1, 32);
			}
			else
			{
				p->current_resp_type = 0xff;
			}
			break;
		case PROT_CMD_HANDSHAKE:		//握手指令
			WD_DBG("received PROT_CMD_HANDSHAKE response.\r\n");
			p->current_resp_cmd = PROT_CMD_HANDSHAKE;
			dev_param->handshake_state = 1;
			break;
		case PROT_CMD_CHECKSENSOR:break;	//校验传感器
		case PROT_CMD_IIC_LED_CONTROL:break;//IIC接口灯光控制
		case PROT_CMD_PS_PC_STATE:	//设置pc低功耗状态应答
			WD_DBG("received PROT_CMD_PS_PC_STATE response.\r\n");
			p->current_resp_cmd = PROT_CMD_PS_PC_STATE;
			break;
		case PROT_CMD_TEST_TYPE:	//生产测试命令
			D_DBG("received PROT_CMD_TEST_TYPE response.\n");
			p->current_resp_cmd = PROT_CMD_TEST_TYPE;
			switch(p->current_sub_cmd_code)
			{
				case PROT_SUBCMD_READ_FW:
					if(26 == len)
					{
						dev_param->onekey_powerup.continue_read_fw_version_flag = 0;
						memcpy(dev_param->firmware_version, &buf[1], len-1);
						dev_param->firmware_version[len] = '\0';
						D_DBG("len-1 =  %d\n", len-1);
						WD_LOG("firmware_version is %s\n", dev_param->firmware_version);

						sscanf(dev_param->firmware_version, "acm32_btl_ofilm_pc_%d", &(dev_param->firmware_version_num));
						WD_LOG("firmware_version num is %d\n", dev_param->firmware_version_num);
					}
					else
					{
						dev_param->onekey_powerup.continue_read_fw_version_flag = 1;
						WD_LOG("not received firmware_version!!!\n");
						if((6 == len)&&(0x05 == buf[1]))
						{
							set_onekey_powerup_flag(1);
							gettimeofday(&(dev_param->onekey_powerup.tv_current_time), NULL);//若读取到1键开机结果，15秒后未解锁则清空一键开机状态

							if(0x00 == buf[0])
							{
								dev_param->onekey_powerup.search_num = 1;
								dev_param->onekey_powerup.search_id[0] = ((buf[2] << 8) & 0xff00) | (buf[3] & 0xff);
								dev_param->onekey_powerup.search_id[1] = 0xffff;
							}
							else
							{
								WD_DBG("identify failed!\n");
								dev_param->onekey_powerup.search_num = 0;
								dev_param->onekey_powerup.search_id[0] = 0xffff;
							}
							WD_DBG("search_num = %d, search_id[0] = 0x%04x.\n", \
								dev_param->onekey_powerup.search_num, dev_param->onekey_powerup.search_id[0]);
						}
						else if((6 <= len)&&(0xf5 == buf[1]))
						{
							set_onekey_powerup_flag(1);
							gettimeofday(&(dev_param->onekey_powerup.tv_current_time), NULL);//若读取到1键开机结果，10秒后未解锁则清空一键开机状态
							if(0x00 == buf[0])
							{
								dev_param->onekey_powerup.search_num = buf[2];
								for(int n = 0; n < dev_param->onekey_powerup.search_num; n++)
								{
									dev_param->onekey_powerup.search_id[n] = buf[3 + n];
								}
								dev_param->onekey_powerup.search_id[dev_param->onekey_powerup.search_num] = 0xffff;
							}
							else
							{
								WD_DBG("identify failed!\n");
								dev_param->onekey_powerup.search_num = 0;
								dev_param->onekey_powerup.search_id[0] = 0xffff;
							}

							WD_DBG("search_num = %d, search_id[0] = %d.\n", \
								dev_param->onekey_powerup.search_num, dev_param->onekey_powerup.search_id[0]);
						}
					}
					break;
				default:
					break;
			}
			break;			//生产测试命令

		/*********************用于BF91360ML*********************/
		case PORT_CMD_SET_BRIGHTNESS:break; 	//设置采集器亮度, add by hcq, 20221229
		case PORT_CMD_GET_BRIGHTNESS:		 	//获取采集器当前亮度
#if 0
			if(PROT_RESP_OK == confirm_code)
			{
				uint16 brightness = ((buf[1] << 8) & 0xff00) | (buf[2] & 0xff);
				p->current_resp_type = PROT_RESP_OK;

				DBG("%s:%d:%s: brightness = 0x%04x\r\n", __FILE__, __LINE__, __func__, brightness);
			}
#endif
			break;
		case PORT_CMD_SET_CONTRAST:break;		//设置采集器当前对比度
		case PORT_CMD_GET_CONTRAST:break;		//获取采集器当前对比度
		case PORT_CMD_GET_MAXSIZEOFIMAGE:break; //获取采集器图片尺寸最大值
		case PORT_CMD_SET_SIZEOFIMAGE:break;	//设置采集器当前图片坐标X，坐标Y，宽度，高度
		case PORT_CMD_GET_SIZEOFIMAGE:break;	//获取采集器当前图片坐标X，坐标Y，宽度，高度
		case PORT_CMD_READYCAPIMAGE:break;		//准备采集一帧图像
		case PORT_CMD_STARTCAPIMAGE:			//采集一帧图像
			if(CONFIRM_CODE_SUCCESS == confirm_code)
			{
				D_DBG("start capture.\r\n");
				p->current_resp_type = PROT_RESP_OK;
				p->current_resp_cmd = PORT_CMD_STARTCAPIMAGE;
			}
			else
			{
				D_DBG("capture failed!!!\r\n");
				p->current_resp_type = confirm_code;
				p->current_resp_cmd = PORT_CMD_STARTCAPIMAGE;
			}
			break;
		case PORT_CMD_ENDCAPIMAGE:break;		//结束采集一帧图像
		/*******************************************************/

		case PROT_CMD_RTBOOT: //返回boot状态，便于下次重烧固件
			WD_DBG("received PROT_CMD_RTBOOT response.\n");
			p->current_resp_cmd = PROT_CMD_RTBOOT;
			break;
		default:
			WD_ERR("not find the current_cmd_code 0x%02x, error!!!\r\n", current_cmd_code);
			return DRV_ERR;
	}

	return DRV_OK;
}

int32 fp_parse_prot_data_end(uint8 *buf, int32 len)
{
	uint8 current_cmd_code = prot_packet_usb.current_cmd_code;
	FP_DEVICE_PARAM_STRUCT *dev_param = &fp_device_param;
	int32 ret = DRV_OK;

	if((NULL == buf) || (0 >= len))
	{
		WD_ERR("the param is error!!!\r\n");
		return DRV_ERR;
	}

	switch(current_cmd_code)
	{
		case PROT_CMD_READINFOPAGE:
			if(FLASH_INFO_PAGE_SIZE != len)
			{
				WD_ERR("len = %d, error!!!\r\n", len);
			}
			WD_DBG("acquire flash_info_page data:\r\n");
			{
				int n = len;
				//(len > 64)?(n = 64):(n = len);
				for(int i = 0; i < n; i++)
				{
					W_DBG("%02x ", buf[i]);
					if(0 == ((i+1)%32))
						DBG("\r\n");
				}
				W_DBG("\r\n");
			}

			if(FLASH_INFO_PAGE_SIZE >= len)
			{
				memcpy(dev_param->flash_info_page, buf, len);
			}
			break;
		case PORT_CMD_ACQUIRE_IMAGEDATA:
			if(IMG_SIZE != len)
			{
				WD_ERR("len = %d, error!!!\r\n", len);
			}
			DBG("%s:%d:%s: acquire image data:\r\n", __FILE__, __LINE__, __func__);
			{
				int n;
				(len > 64)?(n = 64):(n = len);
				for(int i = 0; i < n; i++)
				{
					DBG("%02x ", buf[i]);
					if(0 == ((i+1)%32))
						DBG("\r\n");
				}
				DBG("\r\n");
			}
			memcpy(dev_param->img_data, buf, len);
			break;
		default:
			WD_ERR("not find the current_cmd_code 0x%02x, error!!!\r\n", current_cmd_code);
			ret = DRV_ERR;
			break;
	}

	return ret;
}



int32 fp_parse_prot_head(uint8 *buf, int32 len)
{
	PROT_PACKET *p = NULL;
	int32 ret = DRV_OK;

	if((NULL == buf) || (sizeof(PROT_PACKET) != len))
	{
		WD_ERR("the param is error!!!\r\n");
		return DRV_ERR;
	}

	p = (PROT_PACKET *)buf;

	switch(p->prot_type)
	{
		case PROT_TYPE_CMD: break;
		case PROT_TYPE_DATA: break;
		case PROT_TYPE_RESPOND:
			fp_parse_prot_response(p->prot_data, p->prot_data_cnt);
			break;
		case PROT_TYPE_END:
			fp_parse_prot_data_end(p->prot_data, p->prot_data_cnt);
			break;
		default:
			WD_ERR("p->prot_type = 0x%02x is error!!!\r\n", p->prot_type);
			ret = DRV_ERR;
			break;
	}

	return ret;
}

/*对USB的命令数据进行处理*/
int32 fp_deal_usb_data(uint8 value)
{
	uint8 getchar = 0;
	uint16 sum[4] = {0};
	uint16 checksum = 0;
	int32 ret = DRV_ERR;
	PROT_PACKET *p = NULL;

	p = &prot_packet_usb;

	getchar = value;

	switch (p->prot_state)
	{
		case PACKET_IDLE:
			if (getchar == 0xEF)
			{
				p->prot_state = PACKET_HEAD;

				usb_recv_cnt = 0;
				usb_recv_data[usb_recv_cnt++]=getchar;
			}
			break;
		case PACKET_HEAD:
			if (getchar == 0x01)
			{
				p->prot_head = 0xEF01;
				p->prot_state = PACKET_ADDRESS1;

				usb_recv_data[usb_recv_cnt++]=getchar;
			}
			else
			{
				p->prot_state = PACKET_IDLE;	//包头错误，转初始状态
			}
			break;
		case PACKET_ADDRESS1:
			p->prot_addr  = 0;
			p->prot_addr |= getchar;
			p->prot_addr <<=8;
			p->prot_state = PACKET_ADDRESS2;

			usb_recv_data[usb_recv_cnt++]=getchar;
			break;
		case PACKET_ADDRESS2:
			p->prot_addr |= getchar;
			p->prot_addr <<=8;
			p->prot_state = PACKET_ADDRESS3;

			usb_recv_data[usb_recv_cnt++]=getchar;
			break;
		case PACKET_ADDRESS3:
			p->prot_addr |= getchar;
			p->prot_addr <<=8;
			p->prot_state = PACKET_ADDRESS4;

			usb_recv_data[usb_recv_cnt++]=getchar;
			break;
		case PACKET_ADDRESS4:
			p->prot_addr |= getchar;
			p->prot_state = PACKET_TYPE;
			usb_recv_data[usb_recv_cnt++]=getchar;
			break;
		case PACKET_TYPE:
			p->prot_type = getchar;
			p->prot_state = PACKET_SIZE1;

			usb_recv_data[usb_recv_cnt++]=getchar;
			break;
		case PACKET_SIZE1:
			p->prot_size  = 0;
			p->prot_size |= getchar;
			p->prot_size <<=8;
			p->prot_state = PACKET_SIZE2;

			usb_recv_data[usb_recv_cnt++]=getchar;
			break;
		case PACKET_SIZE2:	//包长度 = 数据内容长度 + 校验位长度
			p->prot_size |= getchar;
			p->prot_data_cnt = 0;
			if (p->prot_size > 2)				//有数据
			{
				p->prot_state = PACKET_DATA;
			}
			else if (p->prot_size == 2)	//无数据，直接到校验位
			{
				p->prot_state = PACKET_CHECKSUM1;
			}
			else
			{
				p->prot_state = PACKET_IDLE;
			}

			usb_recv_data[usb_recv_cnt++] = getchar;
			break;
		case PACKET_DATA:
 			p->prot_data[p->prot_data_cnt] = getchar;
 			p->prot_data_cnt++;
			if((PORT_CMD_ACQUIRE_IMAGEDATA == p->current_cmd_code) && (0xffff == p->prot_size))
			{
				if(IMG_SIZE <= p->prot_data_cnt)
				{
					p->prot_state = PACKET_CHECKSUM1;
				}
			}
			else
			{
				if((p->prot_size-2) <= p->prot_data_cnt)
	 			{
	 				p->prot_state = PACKET_CHECKSUM1;
	 			}
			}

			usb_recv_data[usb_recv_cnt++]=getchar;
			break;
		case PACKET_CHECKSUM1:
			p->prot_checksum  =0;
			p->prot_checksum |=getchar;
			p->prot_checksum <<=8;
			p->prot_state = PACKET_CHECKSUM2;

			usb_recv_data[usb_recv_cnt++]=getchar;
			break;
		case PACKET_CHECKSUM2:
			p->prot_checksum |=getchar;
			usb_recv_data[usb_recv_cnt++]=getchar;
			sum[0] = p->prot_type;
			sum[1] = (p->prot_size & 0xFF00)>>8;
			sum[2] = (p->prot_size & 0xFF);
			sum[3] = get_check_sum(p->prot_data, p->prot_data_cnt);

			checksum = (sum[0]+sum[1]+sum[2]+sum[3])&0xFFFF;

	 		if((checksum == p->prot_checksum) \
				|| ((PORT_CMD_ACQUIRE_IMAGEDATA == p->current_cmd_code) && (CAP_PARAM_VALID_FLAG == p->prot_checksum)))
	 		{
				p->prot_respond = PROT_RESP_OK;

				if (usb_recv_cnt > 0)
				{
				    if (1)//add by hcq, 20221226
					{
						int i = 0;
						int n;
						WD_DBG("Recv data from device: %d\n", usb_recv_cnt);
						(usb_recv_cnt > 64)?(n = 64):(n = usb_recv_cnt);
						for (i = 0; i < n; i++)
						{
							W_DBG("%02x ", usb_recv_data[i]);
							if(0 == (i + 1) % 32)
								W_DBG("\n");
						}
						W_DBG("\n");
					}
					fp_parse_prot_head((uint8 *)p, sizeof(PROT_PACKET));
					usb_recv_cnt=0;
				}
				ret = DRV_OK;
	 		}
			else
			{
				WD_ERR("p->prot_checksum = 0x%04x, checksum = 0x%04x, not equal!!!\r\n", p->prot_checksum, checksum);
			}
			p->prot_state = PACKET_IDLE;
			break;
		default:
			break;
	}

	return ret;
}


int32 fp_parse_prot(uint8 *buf, int32 len)
{
	int32 i = 0;
	int32 ret = DRV_ERR;

	if((NULL == buf) || (0 >= len))
	{
		WD_ERR("the param is error!!!\r\n");
		return DRV_ERR;
	}


    DBG("fp_parse_prot buf: len: %d \n", len);
    int n = 0;
    (len > 64)?(n = 64):(n = len);

    for (i = 0; i < n; i++)
    {
        DBG("%02x ", buf[i]);
        if(0 == (i + 1) % 32)
            DBG("\n");
    }
    W_DBG("\n");


	for(i = 0; i < len; i++)
	{
		if(DRV_OK == fp_deal_usb_data(buf[i]))
		{
			ret = DRV_OK;
			//break;
		}
	}

	return ret;
}




int32 fp_fill_msg_head(MSG_HEAD_STRUCT *head, uint8 pkg_flag, uint16 cmd_len)
{
	if(NULL == head)
	{
		WD_ERR("the param is error!!!\r\n");
		return DRV_ERR;
	}

    head->pkg_head = htons(0xEF01);
    head->chip_addr = htonl(0xFFFFFFFF);
	head->pkg_flag = pkg_flag;
	head->pkg_len = htons(cmd_len);

	return DRV_OK;
}

int32 fp_fill_msg_checksum(uint8 *buf, int32 len)
{
	uint16 checksum = 0;

	if((NULL == buf) || (0 >= len))
	{
		WD_ERR("the param is error!!!\r\n");
		return DRV_ERR;
	}

	checksum = get_check_sum(buf, len);
    buf[len] = (checksum >> 8) & 0xff;//校验和
    buf[len + 1] = checksum & 0xff;//校验和

	return DRV_OK;
}

int32 fp_read_and_parse_prot(int32 len)
{
	MSG_STRUCT msg;
	int32 read_len = len;

	if(0 >= len)
	{
		WD_ERR("the param is error!!!\r\n");
		return DRV_ERR;
	}

	memset((int8 *)&msg, 0, sizeof(MSG_STRUCT));

	if(DRV_OK != usb_read_data((uint8 *)&msg, read_len, &read_len))
	{
		WD_ERR("usb_read_data failed!!!\r\n");
		return DRV_ERR;
	}

	if(DRV_OK != fp_parse_prot((uint8 *)&msg, read_len))
	{
		ERR("%s:%d:%s: fp_parse_prot failed!!!\r\n", __FILE__, __LINE__, __func__);
		return DRV_ERR;
	}
    DBG("fp_read_and_parse_prot successful \n");

	return DRV_OK;
}

//发送命令并读取应答
//cmd_code: 命令码, recv_len: 待接收数据长度, wait_ms发送命令后的等待应答时间, cycle_ms: 未读取数据时循环时间, cycle_times未读取到数据时循环次数
int32 fp_send_cmd(uint8 cmd_code, uint8 *buf, int32 len, RECV_DATA_STRUCT recv_param)
{
	MSG_STRUCT msg;
	int32 index = 0;
	int32 wr_len = 0;//write or read len
	PROT_PACKET *p = &prot_packet_usb;
	int ret = DRV_OK;

	memset((int8 *)&msg, 0, sizeof(MSG_STRUCT));

    msg.data[index++] = cmd_code;//指令码
    //p->current_cmd_code = cmd_code;

	if((NULL != buf) && (0 < len))
	{
		memcpy((uint8 *)(&(msg.data[index])), buf, len);
		index += len;
	}

    fp_fill_msg_head(&msg.head, PROT_TYPE_CMD, index + CHIP_CHECKSUM_SIZE);
	fp_fill_msg_checksum((uint8 *)&msg.head.pkg_flag, \
			sizeof(msg.head.pkg_flag) + sizeof(msg.head.pkg_len) + index);
	index += CHIP_CHECKSUM_SIZE;

	if(DRV_OK != usb_send_data((uint8 *)&msg, sizeof(MSG_HEAD_STRUCT) + index, &wr_len))
	{
		WD_ERR("usb_send_data failed!!!\r\n");
		return DRV_ERR;
	}

	if(0 < recv_param.wait_ms)
		usleep(recv_param.wait_ms * 1000);

	ret = DRV_ERR;
	for(int i = 0; i < recv_param.cycle_times; i++)
	{
		fp_resp_init(cmd_code);

		if(DRV_OK == fp_read_and_parse_prot(recv_param.recv_len))
		{
			ret = DRV_OK;
			break;
		}

		if(recv_param.cycle_ms)
		{
			usleep(recv_param.cycle_ms * 1000);
		}
	}

	if(DRV_OK == ret)
	{
		if(p->current_cmd_code != p->current_resp_cmd) //|| (PROT_RESP_OK != p->current_resp_type))
		{
			WD_ERR("current_cmd_code = 0x%02x, current_resp_cmd = 0x%02x, ERROR!!!\r\n", \
				p->current_cmd_code, p->current_resp_cmd);
			ret = DRV_ERR;
		}
	}

	return ret;
}

struct timeval *get_onekey_powerup_tv_time(void)			//一键开机读取到的时间
{
	FP_DEVICE_PARAM_STRUCT *dev_param = &fp_device_param;
	return &(dev_param->onekey_powerup.tv_current_time);
}

uint8 get_onekey_powerup_flag(void)	//获取一键开机标志
{
	FP_DEVICE_PARAM_STRUCT *dev_param = &fp_device_param;
	return dev_param->onekey_powerup.onekey_powerup_flag;
}

int32 set_onekey_powerup_flag(uint8 flag)	//设置一键开机标志
{
	FP_DEVICE_PARAM_STRUCT *dev_param = &fp_device_param;
	dev_param->onekey_powerup.onekey_powerup_flag = flag;
	return DRV_OK;
}

uint16 *get_onekey_powerup_search_id(void)
{
	FP_DEVICE_PARAM_STRUCT *dev_param = &fp_device_param;
	return dev_param->onekey_powerup.search_id;
}

int32 init_onekey_powerup_search_id(void)
{
	FP_DEVICE_PARAM_STRUCT *dev_param = &fp_device_param;

	for(int i = 0; i < ENROLL_NUM_MAX; i++)
	{
		dev_param->onekey_powerup.search_id[i] = 0xffff;
	}

	return DRV_OK;
}

int32 get_onekey_powerup_search_num(void)
{
	FP_DEVICE_PARAM_STRUCT *dev_param = &fp_device_param;
	return dev_param->onekey_powerup.search_num;
}

uint8 get_onekey_restart_flag(void)	//获取一键开机标志
{
	FP_DEVICE_PARAM_STRUCT *dev_param = &fp_device_param;
	return dev_param->onekey_powerup.onekey_restart_flag;
}

int32 set_onekey_restart_flag(uint8 flag)	//设置一键开机标志
{
	FP_DEVICE_PARAM_STRUCT *dev_param = &fp_device_param;
	dev_param->onekey_powerup.onekey_restart_flag = flag;
	return DRV_OK;
}

int32 get_restart_tv_begin_change_ms(void)
{
	FP_DEVICE_PARAM_STRUCT *dev_param = &fp_device_param;
	struct timeval tv_end;
	struct timeval tv_begin = dev_param->onekey_powerup.tv_restart_begin;
	int verify_time_ms = 0;

	gettimeofday(&tv_end, NULL);

	if(tv_end.tv_usec > tv_begin.tv_usec)
	{
		verify_time_ms = (tv_end.tv_sec - tv_begin.tv_sec)*1000 +\
			(tv_end.tv_usec - tv_begin.tv_usec)/1000;
	}
	else
	{
		verify_time_ms = (tv_end.tv_sec - tv_begin.tv_sec - 1)*1000 +\
			(tv_end.tv_usec + 1000*1000 - tv_begin.tv_usec)/1000;
	}

	return verify_time_ms;
}


//获取固件版本
int32 fp_get_firmware_version(void)
{
	FP_DEVICE_PARAM_STRUCT *dev_param = &fp_device_param;
	RECV_DATA_STRUCT recv_param;
	uint8 buf[10] = {0};

	WD_DBG("send PROT_CMD_TEST_TYPE PROT_SUBCMD_READ_FW command.\r\n");

	//fp_recv_param_init(&recv_param, 64, 10, 10, 10);
	fp_recv_param_init(&recv_param, 64, 20, 10, 20);//循环时间由10ms改为20ms, add by hcq, 20230608 08:15

	buf[0] = PROT_SUBCMD_READ_FW;
	prot_packet_usb.current_sub_cmd_code = PROT_SUBCMD_READ_FW;

	if(DRV_OK != fp_send_cmd(PROT_CMD_TEST_TYPE, buf, 1, recv_param))
	{
		WD_ERR("fp_send_cmd failed!!!\r\n");
		for(int count = 0; count < 5; count++)
		{
			usleep(20 * 1000);
			if(1 != dev_param->onekey_powerup.continue_read_fw_version_flag)
			{
				break;
			}

			if(DRV_OK != fp_read_and_parse_prot(recv_param.recv_len))
			{
				break;
			}
		}
		dev_param->onekey_powerup.continue_read_fw_version_flag = 0;
		return DRV_ERR;
	}

	for(int count = 0; count < 5; count++)
	{
		usleep(20 * 1000);
		if(1 != dev_param->onekey_powerup.continue_read_fw_version_flag)
		{
			break;
		}

		if(DRV_OK != fp_read_and_parse_prot(recv_param.recv_len))
		{
			break;
		}
	}
	dev_param->onekey_powerup.continue_read_fw_version_flag = 0;

	switch(fp_resp_type_get())
	{
		case PROT_RESP_OK:
			DBG("%s:%d:%s: received PROT_RESP_OK.\r\n", __FILE__, __LINE__, __func__);
			break;
		default:
			WD_ERR("not received PROT_RESP_OK!!!\r\n");
			return DRV_ERR;
	}

	return DRV_OK;
}

//获取固件版本
char *fp_return_firmware_version(void)
{
	FP_DEVICE_PARAM_STRUCT *dev_param = &fp_device_param;
	return dev_param->firmware_version;
}

//获取固件版本
uint32 fp_return_firmware_version_num(void)
{
	FP_DEVICE_PARAM_STRUCT *dev_param = &fp_device_param;
	return dev_param->firmware_version_num;
}




//验证用获取图像
int32 fp_get_fprint_img(void)
{
	RECV_DATA_STRUCT recv_param;

	D_DBG("send PROT_CMD_GETIMAGE command.\n");//未采集到指纹时该指令会循环发送，故不写入log信息

	//fp_recv_param_init(&recv_param, 64, 100, 10, 10);
	fp_recv_param_init(&recv_param, 64, 100, 10, 20);//循环时间由10ms改为20ms, add by hcq, 20230608 08:15

	if(DRV_OK == fp_send_cmd(PROT_CMD_GETIMAGE, NULL, 0, recv_param))
	{
		switch(fp_resp_type_get())
		{
			case PROT_RESP_OK:
				WD_LOG("received PROT_RESP_OK.\r\n");
				fp_upload_fprint_img();
				break;
			default:
				WD_ERR("not received PROT_RESP_OK!!!\r\n");
				return DRV_ERR;
		}
	}

	return DRV_OK;
}

//上传图像
int32 fp_upload_fprint_img(void)
{
	RECV_DATA_STRUCT recv_param;

	WD_DBG("send PROT_CMD_UPIMAGE command.\n");

	//fp_recv_param_init(&recv_param, 64, 10, 5, 10);
	fp_recv_param_init(&recv_param, 64, 20, 5, 20);//循环时间由10ms改为20ms, add by hcq, 20230608 08:15

	if(DRV_OK == fp_send_cmd(PROT_CMD_UPIMAGE, NULL, 0, recv_param))
	{
		switch(fp_resp_type_get())
		{
			case PROT_RESP_OK:
				D_DBG("received PROT_RESP_OK.\n");
				prot_packet_usb.current_cmd_code = PORT_CMD_ACQUIRE_IMAGEDATA;

				if(DRV_ERR == fp_read_and_parse_prot(IMG_SIZE + 20))
				{
					WD_ERR("fp_read_and_parse_prot failed!!!\r\n");
					return DRV_ERR;
				}
				break;
			default:
				WD_ERR("not received PROT_RESP_OK!!!\r\n");
				return DRV_ERR;
		}
	}

	return DRV_OK;
}

//读系统参数
int32 fp_read_sys_param(void)
{
	RECV_DATA_STRUCT recv_param;

	WD_DBG("send PROT_CMD_READSYSPARA command.\n");

	//fp_recv_param_init(&recv_param, 64, 10, 3, 10);
	fp_recv_param_init(&recv_param, 64, 20, 3, 20);//循环时间由10ms改为20ms, add by hcq, 20230608 08:15

	if(DRV_OK == fp_send_cmd(PROT_CMD_READSYSPARA, NULL, 0, recv_param))
	{
		switch(fp_resp_type_get())
		{
			case PROT_RESP_OK:
				D_DBG("received PROT_RESP_OK.\r\n");
				break;
			default:
				WD_ERR("not received PROT_RESP_OK!!!\r\n");
				return DRV_ERR;
		}
	}

	return DRV_OK;
}


//设置芯片地址
int32 fp_set_chip_addr(uint32 chip_addr)
{
	RECV_DATA_STRUCT recv_param;
	uint8 buf[10] = {0};
	int index = 0;

	WD_DBG("send PROT_CMD_SETCHIPADDR command.\n");

	//fp_recv_param_init(&recv_param, 64, 10, 3, 10);
	fp_recv_param_init(&recv_param, 64, 20, 3, 20);//循环时间由10ms改为20ms, add by hcq, 20230608 08:15

	buf[index++] = (chip_addr >> 24) & 0xff;
	buf[index++] = (chip_addr >> 16) & 0xff;
	buf[index++] = (chip_addr >> 8) & 0xff;
	buf[index++] = chip_addr & 0xff;

	if(DRV_OK == fp_send_cmd(PROT_CMD_SETCHIPADDR, buf, index, recv_param))
	{
		switch(fp_resp_type_get())
		{
			case PROT_RESP_OK:
				DBG("%s:%d:%s: received PROT_RESP_OK.\r\n", __FILE__, __LINE__, __func__);
				break;
			default:
				WD_ERR("not received PROT_RESP_OK!!!\r\n");
				return DRV_ERR;
		}
	}

	return DRV_OK;
}

//读Flash信息页
int32 fp_read_flash_info_page(void)
{
	RECV_DATA_STRUCT recv_param;

	WD_DBG("send PROT_CMD_READINFOPAGE command.\n");

	//fp_recv_param_init(&recv_param, 64, 10, 5, 10);
	fp_recv_param_init(&recv_param, 64, 20, 5, 20);//循环时间由10ms改为20ms, add by hcq, 20230608 08:15

	if(DRV_OK == fp_send_cmd(PROT_CMD_READINFOPAGE, NULL, 0, recv_param))
	{
		switch(fp_resp_type_get())
		{
			case PROT_RESP_OK:
				D_DBG("received PROT_RESP_OK.\n");
				//待增加flash信息读取, by hcq, 20230129
				if(DRV_ERR == fp_read_and_parse_prot(FLASH_INFO_PAGE_SIZE + 20))
				{
					WD_ERR("fp_read_and_parse_prot failed!!!\r\n");
					return DRV_ERR;
				}
				break;
			default:
				WD_ERR("not received PROT_RESP_OK!!!\r\n");
				return DRV_ERR;
		}
	}

	return DRV_OK;
}


//读索引表
int32 fp_read_index_table(uint8 index_page)
{
	RECV_DATA_STRUCT recv_param;
	uint8 buf[10] = {0};

	WD_DBG("send PROT_CMD_READINDEXTABLE command.\n");

	//fp_recv_param_init(&recv_param, 64, 10, 10, 10);
	fp_recv_param_init(&recv_param, 64, 20, 10, 20);//循环时间由10ms改为20ms, add by hcq, 20230608 08:15

	buf[0] = index_page;

	if(DRV_OK != fp_send_cmd(PROT_CMD_READINDEXTABLE, buf, 1, recv_param))
	{
		WD_ERR("fp_send_cmd failed!!!\r\n");
		return DRV_ERR;
	}

	switch(fp_resp_type_get())
	{
		case PROT_RESP_OK:
			D_DBG("received PROT_RESP_OK.\n");
			break;
		default:
			WD_ERR("not received PROT_RESP_OK!!!\r\n");
			return DRV_ERR;
	}


	return DRV_OK;
}


//获取芯片唯一序列号
int32 fp_get_chip_serial_num(void)
{
	RECV_DATA_STRUCT recv_param;
	FP_DEVICE_PARAM_STRUCT *dev_param = &fp_device_param;

	WD_DBG("send PROT_CMD_GETCHIPSN command.\n");

	//fp_recv_param_init(&recv_param, 64, 10, 3, 10);
	fp_recv_param_init(&recv_param, 64, 20, 3, 20);//循环时间由10ms改为20ms, add by hcq, 20230608 08:15

	if(DRV_OK == fp_send_cmd(PROT_CMD_GETCHIPSN, NULL, 0, recv_param))
	{
		switch(fp_resp_type_get())
		{
			case PROT_RESP_OK:
				D_DBG("received PROT_RESP_OK.\n");
				{
					WD_DBG("chip_serial_num: ");
					for(int i = 0; i < dev_param->chip_serial_num_len; i++)
					{
						W_DBG("%02x ", dev_param->chip_serial_num[i]);
					}
					W_DBG("\n");
				}
				break;
			default:
				WD_ERR("not received PROT_RESP_OK!!!\r\n");
				return DRV_ERR;
		}
	}

	return DRV_OK;
}



int32 fp_handshake(void)
{
	RECV_DATA_STRUCT recv_param;
	FP_DEVICE_PARAM_STRUCT *dev_param = &fp_device_param;

	WD_DBG("send PROT_CMD_HANDSHAKE command.\n");

	//fp_recv_param_init(&recv_param, 230, 10, 3, 10);//此处长度未遵循协议，待确认, by hcq, 20230129
	fp_recv_param_init(&recv_param, 230, 20, 3, 20);//循环时间由10ms改为20ms, add by hcq, 20230608 08:15

	dev_param->handshake_state = 0;

	if(DRV_OK == fp_send_cmd(PROT_CMD_HANDSHAKE, NULL, 0, recv_param))
	{
		switch(fp_resp_type_get())
		{
			case PROT_RESP_OK:
				D_DBG("received PROT_RESP_OK.\n");
				D_DBG("handshake_state = %d.\n", dev_param->handshake_state);
				break;
			default:
				WD_ERR("not received PROT_RESP_OK!!!\r\n");
				return DRV_ERR;
		}
	}

	return DRV_OK;
}

uint16 fp_get_empty_enroll_id(void)
{
	FP_DEVICE_PARAM_STRUCT *dev_param = &fp_device_param;
	uint16 enroll_id = 0xffff;

	for(int page_num = 0; page_num < INDEX_PAGE_NUM; page_num++)
	{
		if(DRV_OK == fp_read_index_table(page_num))
		{
			for(int i = 0; i < 32; i++)
			{
				for(int j = 0; j < 8; j++)
				{
					if((CURRENT_ENROLL_ID_MIN <= (i*8 + j)) \
						&& (CURRENT_ENROLL_ID_MAX >= (i*8 + j)) \
						&& (0x00 == ((dev_param->index_table_info[page_num][i]>>j) & 0x01)))
					{
						enroll_id = i*8 + j;
						return enroll_id;
					}
				}
			}
		}
	}

	return enroll_id;
}

int32 fp_auto_enroll_param_init(FP_AUTOENROLL_PARAM_STRUCT *auto_enroll_param, \
										uint16 enroll_id, uint8 auto_enroll_times)
{
	auto_enroll_param->enroll_id = enroll_id;
	auto_enroll_param->auto_enroll_times = auto_enroll_times;
	auto_enroll_param->validity_check_result = 0xff;
	auto_enroll_param->current_enroll_time = 0;
	auto_enroll_param->current_enroll_flag = 0;
	memset(auto_enroll_param->capture_result, 0xff, AUTOENROLL_TIMES_MAX);
	memset(auto_enroll_param->create_feature_result, 0xff, AUTOENROLL_TIMES_MAX);
	memset(auto_enroll_param->enroll_result, 0xff, AUTOENROLL_TIMES_MAX);
	auto_enroll_param->merge_template_result = 0xff;
	auto_enroll_param->enroll_conflict_result = 0xff;
	auto_enroll_param->store_template_result = 0xff;
	auto_enroll_param->enroll_finish_flag = 0;
	return DRV_OK;
}

uint8 fp_get_current_enroll_time(void)
{
	FP_DEVICE_PARAM_STRUCT *dev_param = &fp_device_param;

	return dev_param->auto_enroll_param.current_enroll_time;
}

uint8 fp_get_enroll_finish_flag(void)
{
	FP_DEVICE_PARAM_STRUCT *dev_param = &fp_device_param;

	return dev_param->auto_enroll_param.enroll_finish_flag;
}

uint8 fp_get_store_template_result(void)
{
	FP_DEVICE_PARAM_STRUCT *dev_param = &fp_device_param;

	return dev_param->auto_enroll_param.store_template_result;
}


uint8 fp_get_enroll_create_feature_result(uint8 enroll_time)
{
	FP_DEVICE_PARAM_STRUCT *dev_param = &fp_device_param;

	if(enroll_time > AUTOENROLL_TIMES_MAX)
	{
		WD_ERR("enroll_time = %d, error!!!\r\n", enroll_time);
		return 0xff;
	}

	return dev_param->auto_enroll_param.create_feature_result[enroll_time];
}

uint8 fp_get_enroll_result(uint8 enroll_time)
{
	FP_DEVICE_PARAM_STRUCT *dev_param = &fp_device_param;

	if(enroll_time > AUTOENROLL_TIMES_MAX)
	{
		WD_ERR("enroll_time = %d, error!!!\r\n", enroll_time);
		return 0xff;
	}

	return dev_param->auto_enroll_param.enroll_result[enroll_time];
}

//自动注册模板开始，发送自动注册模板并获取合法检测应答
int32 fp_auto_enroll_start(uint16 enroll_id, uint8 enroll_times, uint16 param)
{
	RECV_DATA_STRUCT recv_param;
	FP_DEVICE_PARAM_STRUCT *dev_param = &fp_device_param;
	uint8 buf[10] = {0};
	int index = 0;

	WD_DBG("send PROT_CMD_AUTOENROLL command.\n");

	//fp_recv_param_init(&recv_param, 64, 10, 3, 10);
	fp_recv_param_init(&recv_param, 64, 20, 3, 20);//循环时间由10ms改为20ms, add by hcq, 20230608 08:15

	fp_auto_enroll_param_init(&(dev_param->auto_enroll_param), enroll_id, enroll_times);

	buf[index++] = (enroll_id >> 8) & 0xff;
	buf[index++] = enroll_id & 0xff;
	buf[index++] = enroll_times;
	buf[index++] = (param >> 8) & 0xff;
	buf[index++] = param & 0xff;

	if(DRV_OK != fp_send_cmd(PROT_CMD_AUTOENROLL, buf, index, recv_param))
	{
		WD_ERR("fp_send_cmd failed!!!\n");
		return DRV_ERR;
	}


	switch(dev_param->auto_enroll_param.validity_check_result)
	{
		case PROT_RESP_OK:
			D_DBG("received PROT_RESP_OK.\n");
			break;
		case PROT_RESP_ADDR_OUT_RANGE:
		case PROT_RESP_FPRINTLIB_FULL:
			fp_set_ctrlFlag(FP_CONTROL_FLAG_ENROLLID_OUT_RANGE);//录入ID超出范围或存储已满
			WD_ERR("enroll id out of range!!!\n");
			return DRV_ERR;
		default:
			D_DBG("validity_check_result = 0x%02x.\r\n", dev_param->auto_enroll_param.validity_check_result);
			WD_ERR("not received PROT_RESP_OK!!!\n");
			return DRV_ERR;
	}

	return DRV_OK;
}

//获取ms单位的时间增量
int32 fp_get_increment_of_time_ms(struct timeval *tv_old)
{
	struct timeval tv_new;
	long int tv_sec = 0;
	long int tv_usec = 0;
	gettimeofday(&tv_new, NULL);

	if(tv_new.tv_usec < tv_old->tv_usec)
	{
		tv_usec = 1000*1000 + tv_new.tv_usec - tv_old->tv_usec;
		tv_sec = tv_new.tv_sec - 1 - tv_old->tv_sec;
	}
	else
	{
		tv_usec = tv_new.tv_usec - tv_old->tv_usec;
		tv_sec = tv_new.tv_sec - tv_old->tv_sec;
	}

	return (tv_sec*1000*1000 + tv_usec)/1000;
}

//自动注册模板
int32 fp_auto_enroll(int32 timeout_ms)
{
	//RECV_DATA_STRUCT recv_param;
	FP_DEVICE_PARAM_STRUCT *dev_param = &fp_device_param;
	//uint8 buf[10] = {0};
	//int index = 0;

    DBG("fp_auto_enroll=====================>enter\n");
	WD_DBG("start.\n");

	struct timeval tv_current_time;
	gettimeofday(&tv_current_time, NULL);
	while(1)
	{
		fp_read_and_parse_prot(128);	//此处读取字节数应为128，会返回多条应答，若未读取完会出错

		if(0 != dev_param->auto_enroll_param.enroll_finish_flag)
		{
			WD_DBG("received enroll_finish_flag.\n");
			break;
		}

		//设备不存在出错
		if(0 >= fp_get_device_num())
		{
			fp_set_ctrlFlag(FP_CONTROL_FLAG_DEV_NOT_EXIST);
            WD_DBG("received enroll_finish_flag. \n");
			return DRV_ERR;
		}

		if(FP_CONTROL_FLAG_STOPPED == fp_get_ctrlFlag())
		{
            WD_DBG("fp_get_ctrlFlag  FP_CONTROL_FLAG_STOPPED. \n");
			return DRV_ERR;
		}

		if(timeout_ms < fp_get_increment_of_time_ms(&tv_current_time))
		{
			WD_DBG("enroll timeout!!!\n");
			fp_set_ctrlFlag(FP_CONTROL_FLAG_TIMEOUT);
			return DRV_ERR;
		}

		if(0 != dev_param->auto_enroll_param.current_enroll_flag)
		{
			//WD_DBG("fp_auto_enroll one times successful !!!\n");
			WD_DBG("enroll current_enroll_flag!!!\n");
			dev_param->auto_enroll_param.current_enroll_flag = 0;
			break;
		}

		usleep(30 * 1000);
	}
    DBG("fp_auto_enroll=====================>exit\n");

	return DRV_OK;
}

int32 fp_auto_identify_param_init(FP_AUTOIDENTIFY_PARAM_STRUCT *identify_param, \
											uint8 security_level, uint16 identify_id, uint16 param)
{
	identify_param->security_level = security_level;
	identify_param->identify_id = identify_id;
	identify_param->param = param;
	identify_param->validity_check_result = 0xff;
	identify_param->capture_result = 0xff;
	identify_param->search_result = 0xff;
	identify_param->search_num = 0;
	//identify_param->search_id = 0xffff;
	memset((char *)identify_param->search_id, 0xff, sizeof(identify_param->search_num));
	identify_param->score = 0;
	identify_param->identify_finish_flag = 0;
	return DRV_OK;
}

//自动验证指纹
int32 fp_auto_identify(uint8 security_level, uint16 identify_id, uint16 param, uint16 *identify_result_id, int32 timeout_ms)
{
	RECV_DATA_STRUCT recv_param;
	FP_DEVICE_PARAM_STRUCT *dev_param = &fp_device_param;
	uint8 buf[10] = {0};
	int index = 0;
	struct timeval tv_current_time;

	WD_DBG("send PROT_CMD_AUTOIDENTIFY command.\n");

	//fp_recv_param_init(&recv_param, 64, 10, 3, 10);//循环时间由10ms改为20ms
	fp_recv_param_init(&recv_param, 64, 20, 3, 20);//循环时间由10ms改为20ms

	fp_auto_identify_param_init(&(dev_param->auto_identify_param), security_level, identify_id, param);

	buf[index++] = security_level;
	buf[index++] = (identify_id >> 8) & 0xff;
	buf[index++] = identify_id & 0xff;
	buf[index++] = (param >> 8) & 0xff;
	buf[index++] = param & 0xff;

	if(DRV_OK == fp_send_cmd(PROT_CMD_AUTOIDENTIFY, buf, index, recv_param))
	{
		switch(dev_param->auto_identify_param.validity_check_result)
		{
			case PROT_RESP_OK:
				WD_DBG("received PROT_RESP_OK.\n");
				gettimeofday(&tv_current_time, NULL);
				while(1)
				{
					//设备不存在出错
					if(0 >= fp_get_device_num())
					{
						fp_set_ctrlFlag(FP_CONTROL_FLAG_DEV_NOT_EXIST);
						return DRV_ERR;
					}

					if((0 != timeout_ms) && (timeout_ms < fp_get_increment_of_time_ms(&tv_current_time)))
					{
						WD_DBG("identify timeout.\n");
						fp_set_ctrlFlag(FP_CONTROL_FLAG_TIMEOUT);
						return DRV_ERR;
					}

					fp_read_and_parse_prot(64);

					if((0 != dev_param->auto_identify_param.identify_finish_flag) \
						|| (PROT_RESP_OK != dev_param->auto_identify_param.validity_check_result))
					{
						break;
					}

					if(FP_CONTROL_FLAG_STOPPED == fp_get_ctrlFlag())
					{
						fp_onekey_restart_identify(get_onekey_powerup_search_id(), 20);
						return DRV_ERR;
					}

					usleep(20 * 1000);
				}
				break;
			default:
				WD_ERR("not received PROT_RESP_OK!!!\r\n");
				return DRV_ERR;
		}
	}

	if(PROT_RESP_OK != dev_param->auto_identify_param.validity_check_result)
	{
		WD_ERR("validity_check_result = 0x%02x !!!\r\n", \
			dev_param->auto_identify_param.validity_check_result);
		return DRV_ERR;
	}

	WD_DBG("search_result = 0x%02x, search_num = %d, search_id[0] = 0x%04x !!!\r\n", \
			dev_param->auto_identify_param.search_result, dev_param->auto_identify_param.search_num, \
			dev_param->auto_identify_param.search_id[0]);

	if(0 != dev_param->auto_identify_param.search_result)
	{
		WD_ERR("not search id %d !!!\n", identify_id);
		return DRV_OK;
	}

	for(int n = 0; n < dev_param->auto_identify_param.search_num; n++)
	{
		identify_result_id[n] = dev_param->auto_identify_param.search_id[n];
	}

	return DRV_OK;
}

//一键开机自动验证指纹
int32 fp_onekey_powerup_identify(uint8 security_level, uint16 identify_id, uint16 param, uint16 *identify_result_id, int32 wait_ms)
{
	RECV_DATA_STRUCT recv_param;
	FP_DEVICE_PARAM_STRUCT *dev_param = &fp_device_param;
	uint8 buf[10] = {0};
	int index = 0;
	//struct timeval tv_current_time;

	WD_DBG("send PROT_CMD_AUTOIDENTIFY command.\n");

	//fp_recv_param_init(&recv_param, 64, 10, 3, 10);//循环时间由10ms改为20ms
	fp_recv_param_init(&recv_param, 64, 20, 3, 20);//循环时间由10ms改为20ms

	fp_auto_identify_param_init(&(dev_param->auto_identify_param), security_level, identify_id, param);

	buf[index++] = security_level;
	buf[index++] = (identify_id >> 8) & 0xff;
	buf[index++] = identify_id & 0xff;
	buf[index++] = (param >> 8) & 0xff;
	buf[index++] = param & 0xff;

	if(DRV_OK == fp_send_cmd(PROT_CMD_AUTOIDENTIFY, buf, index, recv_param))
	{
		switch(dev_param->auto_identify_param.validity_check_result)
		{
			case PROT_RESP_OK:
				WD_DBG("received PROT_RESP_OK.\n");
				//gettimeofday(&tv_current_time, NULL);
				for(int count = 0; count < 5; count++)
				{
					//设备不存在出错
					if(0 >= fp_get_device_num())
					{
						//fp_set_ctrlFlag(FP_CONTROL_FLAG_DEV_NOT_EXIST);
						return DRV_ERR;
					}

					fp_read_and_parse_prot(64);

					if((0 != dev_param->auto_identify_param.identify_finish_flag) \
						|| (PROT_RESP_OK != dev_param->auto_identify_param.validity_check_result))
					{
						break;
					}

					usleep(wait_ms * 1000);
				}
				break;
			default:
				WD_ERR("not received PROT_RESP_OK!!!\r\n");
				return DRV_ERR;
		}
	}

	if(PROT_RESP_OK != dev_param->auto_identify_param.validity_check_result)
	{
		WD_ERR("validity_check_result = 0x%02x !!!\r\n", \
			dev_param->auto_identify_param.validity_check_result);
		return DRV_ERR;
	}

	WD_DBG("search_result = 0x%02x, search_id[0] = %d.\n", \
			dev_param->auto_identify_param.search_result, dev_param->auto_identify_param.search_id[0]);

	if(0 != dev_param->auto_identify_param.identify_finish_flag)
	{
		set_onekey_powerup_flag(1);
		set_onekey_restart_flag(0);
		gettimeofday(&(dev_param->onekey_powerup.tv_current_time), NULL);//若读取到1键开机结果，15秒后未解锁则清空一键开机状态
	}

	if(0 != dev_param->auto_identify_param.search_result)
	{
		WD_ERR("not search id %d !!!\r\n", \
			identify_id);
		dev_param->onekey_powerup.search_num = 0;
		return DRV_OK;
	}

	dev_param->onekey_powerup.search_num = dev_param->auto_identify_param.search_num;
	for(int n = 0; n < dev_param->auto_identify_param.search_num; n++)
	{
		identify_result_id[n] = dev_param->auto_identify_param.search_id[n];
	}

	return DRV_OK;
}

//uos系统休眠后，按指纹唤醒，调用verify后，在返回结果前会发一次取消，然后重新调用verify，导致一键开机失效
//因此增加保护，记录本次verify结果至一键开机参数中
int32 fp_onekey_restart_identify(uint16 *identify_result_id, int32 wait_ms)
{
	RECV_DATA_STRUCT recv_param;
	FP_DEVICE_PARAM_STRUCT *dev_param = &fp_device_param;
	uint8 buf[10] = {0};
	int index = 0;

	WD_LOG("start.\r\n");

	init_onekey_powerup_search_id();

	for(int count = 0; count < 5; count++)
	{
		//设备不存在出错
		if(0 >= fp_get_device_num())
		{
			//fp_set_ctrlFlag(FP_CONTROL_FLAG_DEV_NOT_EXIST);
			return DRV_ERR;
		}

		fp_read_and_parse_prot(64);

		if((0 != dev_param->auto_identify_param.identify_finish_flag) \
			|| (PROT_RESP_OK != dev_param->auto_identify_param.validity_check_result))
		{
			break;
		}

		usleep(wait_ms * 1000);
	}

	if(PROT_RESP_OK != dev_param->auto_identify_param.validity_check_result)
	{
		WD_ERR("validity_check_result = 0x%02x !!!\r\n", \
			dev_param->auto_identify_param.validity_check_result);
		return DRV_ERR;
	}

	WD_DBG("search_result = 0x%02x, search_id[0] = %d.\n", \
			dev_param->auto_identify_param.search_result, dev_param->auto_identify_param.search_id[0]);

	if(0 != dev_param->auto_identify_param.identify_finish_flag)
	{
		set_onekey_powerup_flag(1);
		set_onekey_restart_flag(1);
		gettimeofday(&(dev_param->onekey_powerup.tv_restart_begin), NULL);
		gettimeofday(&(dev_param->onekey_powerup.tv_current_time), NULL);//若读取到1键开机结果，15秒后未解锁则清空一键开机状态
	}

	if(0 != dev_param->auto_identify_param.search_result)
	{
		WD_ERR("not search id !!!\r\n");
		dev_param->onekey_powerup.search_num = 0;
		return DRV_OK;
	}

	dev_param->onekey_powerup.search_num = dev_param->auto_identify_param.search_num;
	for(int n = 0; n < dev_param->auto_identify_param.search_num; n++)
	{
		identify_result_id[n] = dev_param->auto_identify_param.search_id[n];
	}

	return DRV_OK;
}

int32 fp_onekey_restart_identify_2(uint16 *identify_result_id)
{
	//RECV_DATA_STRUCT recv_param;
	int32 search_num = 0;
	FP_DEVICE_PARAM_STRUCT *dev_param = &fp_device_param;
	//uint8 buf[10] = {0};
	//int index = 0;
	WD_LOG("start.\r\n");

	init_onekey_powerup_search_id();

	set_onekey_powerup_flag(1);
	set_onekey_restart_flag(1);
	gettimeofday(&(dev_param->onekey_powerup.tv_restart_begin), NULL);//读取休眠开机时一键开机时间
	gettimeofday(&(dev_param->onekey_powerup.tv_current_time), NULL);//若读取到1键开机结果，15秒后未解锁则清空一键开机状态


	WD_DBG("search_num = %d.\r\n", search_num);
	for(int n = 0; n < ENROLL_NUM_MAX; n++)
	{
		if(0xffff == identify_result_id[n])
		{
			break;
		}
		dev_param->onekey_powerup.search_id[n] = identify_result_id[n];
		search_num++;
	}

	dev_param->onekey_powerup.search_num = search_num;

	return DRV_OK;
}




int32 fp_delete_template(uint16 enroll_id, uint16 num)
{
	RECV_DATA_STRUCT recv_param;
	FP_DEVICE_PARAM_STRUCT *dev_param = &fp_device_param;
	uint8 buf[10] = {0};
	int index = 0;

	WD_DBG("send PROT_CMD_DELCHAR command.\n");
	WD_DBG("enroll_id = %d, num = %d.\n", enroll_id, num);

	//fp_recv_param_init(&recv_param, 64, 10, 5, 10);
	fp_recv_param_init(&recv_param, 64, 20, 5, 20);//循环时间由10ms改为20ms, add by hcq, 20230608 08:15

	dev_param->delete_template_result = 0xff;

	buf[index++] = (enroll_id >> 8) & 0xff;
	buf[index++] = enroll_id & 0xff;
	buf[index++] = (num >> 8) & 0xff;
	buf[index++] = num & 0xff;

	if(DRV_OK != fp_send_cmd(PROT_CMD_DELCHAR, buf, index, recv_param))
	{
		WD_ERR("fp_send_cmd failed!!!\r\n");
		return DRV_ERR;
	}

	switch(dev_param->delete_template_result)
	{
		case PROT_RESP_OK:
			D_DBG("received PROT_RESP_OK.\r\n");
			break;
		default:
			WD_ERR("delete_template_result = 0x%02x, error!!!\r\n", \
				dev_param->delete_template_result);
			return DRV_ERR;
	}

	return DRV_OK;
}

int32 fp_empty_template(void)
{
	RECV_DATA_STRUCT recv_param;
	FP_DEVICE_PARAM_STRUCT *dev_param = &fp_device_param;

	WD_DBG("send PROT_CMD_EMPTY command.\n");

	//fp_recv_param_init(&recv_param, 64, 10, 5, 10);
	fp_recv_param_init(&recv_param, 64, 20, 5, 20);//循环时间由10ms改为20ms, add by hcq, 20230608 08:15

	dev_param->empty_template_result = 0xff;

	if(DRV_OK == fp_send_cmd(PROT_CMD_EMPTY, NULL, 0, recv_param))
	{
		switch(dev_param->empty_template_result)
		{
			case PROT_RESP_OK:
				DBG("%s:%d:%s: received PROT_RESP_OK.\r\n", __FILE__, __LINE__, __func__);
				break;
			default:
				WD_ERR("empty_template_result = 0x%02x, error!!!\r\n", \
					dev_param->empty_template_result);
				return DRV_ERR;
		}
	}

	return DRV_OK;
}

//删除数据库中不存在的模板id
//输入index_list为数据库中存在的列表
int32 fp_delete_invalid_template(uint8 *index_list)
{
	FP_DEVICE_PARAM_STRUCT *dev_param = &fp_device_param;

	if(NULL == index_list)
	{
		WD_ERR("index_list = NULL, error!!!\r\n");
		return DRV_ERR;
	}


	for(int line = 0; line < INDEX_PAGE_NUM; line++)
	{
		if(DRV_OK != fp_read_index_table(line))
		{
			continue;
		}

		for(int i = 0; i < 32; i++)
		{
			uint8 fp_value = dev_param->index_table_info[line][i];//模组当前字节值
			uint8 db_value = index_list[line*32 + i];//数据库当前字节值
			if(0 == fp_value)
			{
				continue;
			}

			for(int j = 0; j < 8; j++)
			{
				if((CURRENT_ENROLL_ID_MIN <= (256*line + 8*i + j)) && (CURRENT_ENROLL_ID_MAX >= (256*line + 8*i + j)) \
					&& (fp_value & (0x01<<j)) && (!(db_value & (0x01<<j))))
				{
					DBG("%s:%d:%s: index = %d is invalid!!!\r\n", __FILE__, __LINE__, __func__, 256*line + 8*i + j);
					fp_delete_template(256*line + 8*i + j, 1);
				}
			}
		}
	}

	return DRV_OK;
}

int32 fp_set_ctrlFlag(int32 ctrlFlag)
{
	FP_DEVICE_PARAM_STRUCT *dev_param = &fp_device_param;
	dev_param->ctrlFlag = ctrlFlag;

	return DRV_OK;
}

int32 fp_get_ctrlFlag(void)
{
	FP_DEVICE_PARAM_STRUCT *dev_param = &fp_device_param;
	int ctrlFlag = dev_param->ctrlFlag;
    //WD_ERR("fp_get_ctrlFlag ctrlFlag = %d error!!!\r\n",ctrlFlag);

	return ctrlFlag;
}

//清空模组无效报文
int32 fp_read_invalid_pkg(int count)
{
	MSG_STRUCT msg;
	int32 read_len = 64;

	DBG("fp_read_invalid_pkg ===========> enter.\n");

	memset((int8 *)&msg, 0, sizeof(MSG_STRUCT));

	for(int i = 0; i < count; i++)
	{
		if(DRV_OK != usb_read_data((uint8 *)&msg, read_len, &read_len))
		{
			ERR("%s:%d:%s: usb_read_data failed!!!\r\n", __FILE__, __LINE__, __func__);
            DBG("fp_read_invalid_pkg <========================error exit");
			return DRV_ERR;
		}
	}
	DBG("fp_read_invalid_pkg <=========== exit.\n");

	return 0;
}

int32 fp_cancel(void)
{
	RECV_DATA_STRUCT recv_param;
	FP_DEVICE_PARAM_STRUCT *dev_param = &fp_device_param;

	WD_DBG("send PROT_CMD_CANCEL command.\n");

	//fp_recv_param_init(&recv_param, 64, 10, 5, 10);
	fp_recv_param_init(&recv_param, 64, 20, 5, 20);//循环时间由10ms改为20ms, add by hcq, 20230608 08:15

	dev_param->cancel_result = 0xff;

	if(DRV_OK == fp_send_cmd(PROT_CMD_CANCEL, NULL, 0, recv_param))
	{
		switch(dev_param->cancel_result)
		{
			case PROT_RESP_OK:
				D_DBG("received PROT_RESP_OK.\r\n");
				break;
			default:
				WD_ERR("cancel_result = 0x%02x, error!!!\r\n", \
					dev_param->cancel_result);
				fp_read_invalid_pkg(3);//规避取消报文错位，add by hcq, 20230314
				return DRV_ERR;
		}
	}

	fp_read_invalid_pkg(3);//规避取消报文错位，add by hcq, 20230314
	return DRV_OK;
}


int32 fp_sleep(void)
{
	RECV_DATA_STRUCT recv_param;
	FP_DEVICE_PARAM_STRUCT *dev_param = &fp_device_param;

	WD_DBG("send PROT_CMD_SLEEP command.\n");

	dev_param->sleep_result = 0xff;

	//fp_recv_param_init(&recv_param, 64, 10, 3, 10);
	fp_recv_param_init(&recv_param, 64, 20, 3, 20);//循环时间由10ms改为20ms, add by hcq, 20230608 08:15

	if(DRV_OK == fp_send_cmd(PROT_CMD_SLEEP, NULL, 0, recv_param))
	{
		switch(dev_param->sleep_result)
		{
			case PROT_RESP_OK:
				D_DBG("received PROT_RESP_OK.\r\n");
				break;
			default:
				WD_ERR("sleep_result = 0x%02x, error!!!\r\n", \
					dev_param->sleep_result);
				return DRV_ERR;
		}
	}

	return DRV_OK;
}

//读有效模板个数
int32 fp_get_valid_template_num(void)
{
	RECV_DATA_STRUCT recv_param;
	FP_DEVICE_PARAM_STRUCT *dev_param = &fp_device_param;

	WD_DBG("send PROT_CMD_VALIDTEMPLATENUM command.\r\n");

	dev_param->valid_template_num = 0xffff;

	//fp_recv_param_init(&recv_param, 64, 10, 3, 10);
	fp_recv_param_init(&recv_param, 64, 20, 3, 20);//循环时间由10ms改为20ms, add by hcq, 20230608 08:15

	if(DRV_OK == fp_send_cmd(PROT_CMD_VALIDTEMPLATENUM, NULL, 0, recv_param))
	{
		switch(fp_resp_type_get())
		{
			case PROT_RESP_OK:
				DBG("%s:%d:%s: received PROT_RESP_OK.\r\n", __FILE__, __LINE__, __func__);
				DBG("%s:%d:%s: valid_template_num = %d.\r\n", __FILE__, __LINE__, __func__, dev_param->valid_template_num);
				break;
			default:
				WD_ERR("not received PROT_RESP_OK!!!\r\n");
				return DRV_ERR;
		}

	}

	return DRV_OK;
}


//获取采图亮度参数，用于BF91360ML
int32 fp_get_bright(void)
{
	RECV_DATA_STRUCT recv_param;

	//fp_recv_param_init(&recv_param, 64, 10, 3, 10);
	fp_recv_param_init(&recv_param, 64, 20, 3, 20);//循环时间由10ms改为20ms, add by hcq, 20230608 08:15

	if(DRV_OK == fp_send_cmd(PORT_CMD_GET_BRIGHTNESS, NULL, 0, recv_param))
	{
		switch(fp_resp_type_get())
		{
			case PROT_RESP_OK:
				WD_LOG("received PROT_RESP_OK.\r\n");
				break;
			default:
				WD_ERR("not received PROT_RESP_OK!!!\r\n");
				return DRV_ERR;
		}
	}

	return DRV_OK;
}

//强制采图，用于BF91360ML
int32 fp_force_get_fprint_img(void)
{
	RECV_DATA_STRUCT recv_param;
	PROT_PACKET *p = &prot_packet_usb;

	//fp_recv_param_init(&recv_param, 64, 100, 5, 10);
	fp_recv_param_init(&recv_param, 64, 100, 5, 20);//循环时间由10ms改为20ms, add by hcq, 20230608 08:15

	if(DRV_OK == fp_send_cmd(PORT_CMD_STARTCAPIMAGE, NULL, 0, recv_param))
	{
		switch(fp_resp_type_get())
		{
			case PROT_RESP_OK:
				WD_LOG("received PROT_RESP_OK.\r\n");
				p->current_cmd_code = PORT_CMD_ACQUIRE_IMAGEDATA;

				if(DRV_ERR == fp_read_and_parse_prot(IMG_SIZE + 20))
				{
					WD_ERR("fp_read_and_parse_prot failed!!!\r\n");
					return DRV_ERR;
				}

				break;
			default:
				WD_ERR("not received PROT_RESP_OK!!!\r\n");
				return DRV_ERR;
		}
	}

	return DRV_OK;
}

int fp_set_mode(char *mode, int len)
{
	RECV_DATA_STRUCT recv_param;
	uint8 buf[100] = {0};
	int index = 0;

	WD_DBG("send PROT_CMD_SET_MODE command.\n");

	//fp_recv_param_init(&recv_param, 64, 10, 10, 10);
	fp_recv_param_init(&recv_param, 64, 20, 10, 20);//循环时间由10ms改为20ms, add by hcq, 20230608 08:15

	buf[index++] = PROT_SUBCMD_SET_MODE;
	memcpy(&(buf[index]), mode, len);
	index += len;

	if(DRV_OK != fp_send_cmd(PROT_CMD_TEST_TYPE, buf, index, recv_param))
	{
		WD_ERR("fp_send_cmd failed!!!\n");
		return DRV_ERR;
	}

	switch(fp_resp_type_get())
	{
		case PROT_RESP_OK:
			D_DBG("received PROT_RESP_OK.\n");
			break;
		default:
			WD_ERR("not received PROT_RESP_OK!!!\r\n");
			return DRV_ERR;
	}

	return DRV_OK;
}

#define CMD_PARAM_LEN 8
int fp_reboot(void)
{
	RECV_DATA_STRUCT recv_param;
	uint8 cmd_param[CMD_PARAM_LEN] = {0x5A, 0xA5, 0x55, 0xAA, 0x42, 0x44, 0x43, 0x47};
	uint8 buf[100] = {0};
	int index = 0;

	WD_DBG("send PROT_CMD_SET_MODE command.\n");

	//fp_recv_param_init(&recv_param, 64, 10, 10, 10);
	fp_recv_param_init(&recv_param, 64, 70, 1, 0);//发送后只读取一次应答

	memcpy(&(buf[index]), cmd_param, CMD_PARAM_LEN);
	index += CMD_PARAM_LEN;

	if(DRV_OK != fp_send_cmd(PROT_CMD_RTBOOT, buf, index, recv_param))
	{
		WD_ERR("fp_send_cmd failed!!!\n");
		return DRV_ERR;
	}

	switch(fp_resp_type_get())
	{
		case PROT_RESP_OK:
			D_DBG("received PROT_RESP_OK.\n");
			break;
		default:
			WD_ERR("not received PROT_RESP_OK!!!\r\n");
			return DRV_ERR;
	}

	return DRV_OK;
}

int fp_set_pc_state(uint8 pc_state)
{
	RECV_DATA_STRUCT recv_param;
	uint8 buf[100] = {0};
	int index = 0;

	WD_DBG("send PROT_CMD_PS_PC_STATE command.\n");

	//fp_recv_param_init(&recv_param, 64, 10, 3, 10);
	fp_recv_param_init(&recv_param, 64, 20, 3, 20);//循环时间由10ms改为20ms, add by hcq, 20230608 08:15

	buf[index++] = pc_state;

	if(DRV_OK != fp_send_cmd(PROT_CMD_PS_PC_STATE, buf, index, recv_param))
	{
		WD_ERR("fp_send_cmd failed!!!\n");
		return DRV_ERR;
	}

	switch(fp_resp_type_get())
	{
		case PROT_RESP_OK:
			D_DBG("received PROT_RESP_OK.\n");
			break;
		default:
			WD_ERR("not received PROT_RESP_OK!!!\n");
			return DRV_ERR;
	}

	return DRV_OK;
}


#if 0
int ofp1234_discover(void)
{
	//unsigned char buf1[200] = {0x55, 0x53, 0x42, 0x43, 0x00, 0x0c, 0x00, 0x00};
	//unsigned char buf2[200] = {0xef, 0x01, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x03, 0x35, 0x00, 0x39};
	//unsigned char buf3[200] = {0x55, 0x53, 0x42, 0x43, 0x80, 0x80, 0x00, 0x00};

	//int actual_len = 0;

	if(DRV_OK != usb_dev_open())
	{
		return 0;
	}

#if 1
	//fp_handshake();
#else
	libusb_device_handle *handle = usb_dev_param.usbdev_handle;

	if(NULL != handle)
	{
		if(0 == libusb_bulk_transfer(handle, 0x01, buf1, 8, &actual_len, 1000))
		{
			printf("%s:%d:%s: send actual_len = %d: \r\n", __FILE__, __LINE__, __func__, actual_len);
			if(0 == libusb_bulk_transfer(handle, 0x01, buf2, 12, &actual_len, 3000))
			{
				printf("%s:%d:%s: send actual_len = %d: \r\n", __FILE__, __LINE__, __func__, actual_len);
				if(0 == libusb_bulk_transfer(handle, 0x81, buf1, 4, &actual_len, 1000))
				{
					usleep(10 *1000);
					if(0 == libusb_bulk_transfer(handle, 0x01, buf3, 8, &actual_len, 1000))
					{
						libusb_bulk_transfer(handle, 0x81, buf2, 0x80, &actual_len, 1000);
						printf("%s:%d:%s: send actual_len = %d: \r\n", __FILE__, __LINE__, __func__, actual_len);
						for(int i = 0; i < actual_len; i++)
						{
							printf("0x%02x ", buf2[i]);
						}
						printf("\r\n");
						libusb_bulk_transfer(handle, 0x81, buf1, 4, &actual_len, 1000);
					}
				}
			}
		}
	}
	else
    {
        ERR("%s: %s open failed!!!\r\n", __func__, DEV_NAME);
        return DRV_ERR;
    }
#endif
	usb_dev_close();

	return 1;
}
#endif


//获取当前设备数量，0：设备不存在，1：设备存在
int fp_get_device_num(void)
{
	if(NULL == usb_get_dev_handle())
	{
		return 0;
	}
	else
	{
		return 1;
	}
}





int main_test(int argc,char **argv)
{
	if(DRV_OK != fp_module_init())
	{
		WD_ERR("fp_module_init failed.\n");
		return 0;
	}

    /*1. 打开设备文件*/
    if(DRV_OK != usb_dev_module_init())
    {
        WD_ERR("usb_dev_module_init failed.\n");
        return 0;
    }

#if 0
	if(DRV_OK != usb_test())
	{
		ERR("%s:%d:%s: usb_test successfully.\r\n", __FILE__, __LINE__, __func__);
	}
#endif

	while(1)
	{

		//if(DRV_OK != fp_get_bright())
		{
			//usb_test();
		}

		sleep(3);

		//fp_force_get_fprint_img();

		//fp_get_fprint_img();

		//fp_get_chip_serial_num();

		fp_handshake();

		sleep(3);
	}

    return 0;
}

